package yunjiao.designpatterns.command;

import yunjiao.designpatterns.command.commands.Commands;
import yunjiao.designpatterns.command.devices.Appliance;
import yunjiao.designpatterns.command.devices.bedroom.BedRoomFan;
import yunjiao.designpatterns.command.devices.bedroom.BedRoomLight;
import yunjiao.designpatterns.command.devices.kitchen.KitchenLight;
import yunjiao.designpatterns.command.devices.kitchen.Microwave;
import yunjiao.designpatterns.command.devices.livingroom.LivingRoomFan;
import yunjiao.designpatterns.command.devices.livingroom.LivingRoomLight;
import yunjiao.designpatterns.command.devices.livingroom.LivingRoomTV;

import java.util.*;
import java.util.stream.Collectors;


/**
 * TODO
 *
 * @author yangyunjiao
 */
public class HomeAutomation {
    private final Map<Appliance, List<Command>> optionsAvailable = new HashMap<>();

    private HomeAutomation() {
        Appliance bedRoomFan = new BedRoomFan();
        Appliance bedRoomLight = new BedRoomLight();
        Appliance kitchenLight = new KitchenLight();
        Appliance microwave = new Microwave();
        Appliance livingRoomFan = new LivingRoomFan();
        Appliance livingRoomLight = new LivingRoomLight();
        Appliance livingRoomTV = new LivingRoomTV();
        optionsAvailable.put(bedRoomFan,
                Arrays.asList(new Commands.OnCommand("BedRoomFan On", bedRoomFan),
                        new Commands.OffCommand("BedRoomFan Off", bedRoomFan),
                        new Commands.IncreaseSpeedCommand("BedRoomFan Increase", bedRoomFan),
                        new Commands.DecreaseSpeedCommand("BedRoomFan Decrease", bedRoomFan)));

        optionsAvailable.put(bedRoomLight, Arrays.asList(new Commands.OnCommand("BedRoomLight On", bedRoomLight),
                new Commands.OffCommand("BedRoomLight On", bedRoomLight)));

        optionsAvailable.put(kitchenLight, Arrays.asList(new Commands.OnCommand("KitchenLight On", kitchenLight),
                new Commands.OffCommand("KitchenLight Off", kitchenLight)));

        optionsAvailable.put(microwave,
                Arrays.asList(new Commands.OnCommand("Microwave On", microwave), new Commands.OffCommand("Microwave Off", microwave)));

        optionsAvailable.put(livingRoomFan,
                Arrays.asList(new Commands.OnCommand("LivingRoomFan On", livingRoomFan),
                        new Commands.OffCommand("LivingRoomFan Off", livingRoomFan),
                        new Commands.IncreaseSpeedCommand("LivingRoomFan Increase", livingRoomFan),
                        new Commands.DecreaseSpeedCommand("LivingRoomFan Decrease", livingRoomFan)));

        optionsAvailable.put(livingRoomLight, Arrays.asList(new Commands.OnCommand("LivingRoomLight On", livingRoomLight),
                new Commands.OffCommand("LivingRoomLight Off", livingRoomLight)));

        optionsAvailable.put(livingRoomTV,
                Arrays.asList(new Commands.OnCommand("LivingRoomTV On", livingRoomTV),
                        new Commands.OffCommand("LivingRoomTV Off", livingRoomTV),
                        new Commands.TVIncreaseVolumeCommand("LivingRoomTV Increase Volume", livingRoomTV),
                        new Commands.TVIncreaseChannelCommand("LivingRoomTV Decrease Channel", livingRoomTV),
                        new Commands.TVDecreaseVolumeCommand("LivingRoomTV Decrease Volume", livingRoomTV),
                        new Commands.TVDecreaseChannelCommand("LivingRoomTV Decrease Channel", livingRoomTV),
                        new Commands.TVMuteCommand("LivingRoomTV Mute/Unmute", livingRoomTV)));
    }

    public List<String> applianceNames() {
        return optionsAvailable.keySet().stream().map(Appliance::name).collect(Collectors.toList());
    }

    public List<Command> applianceCommands(String applianceName) {
        List<Command> commands = new ArrayList<>();
        if (applianceName != null && !applianceName.trim().isEmpty()) {
            Optional<Appliance> applianceSelected = optionsAvailable.keySet().stream()
                    .filter(appliance -> appliance.name().equalsIgnoreCase(applianceName.trim())).findAny();
            applianceSelected.ifPresent(appliance -> commands.addAll(optionsAvailable.get(appliance)));
        }
        return commands;
    }

    public static HomeAutomation INSTANCE = new HomeAutomation();
}
